package com.roads.supervisor.service.impl;

import com.roads.common.config.MasterConfig;
import com.roads.common.constant.Constants;
import com.roads.common.constant.UserConstants;
import com.roads.common.core.domain.entity.SysUser;
import com.roads.common.utils.DateUtils;
import com.roads.common.utils.SecurityUtils;
import com.roads.common.utils.StringUtils;
import com.roads.common.utils.file.FileUtils;
import com.roads.common.utils.uuid.IdUtils;
import com.roads.project.domain.ProCompany;
import com.roads.project.domain.ProInstitution;
import com.roads.project.domain.ProProject;
import com.roads.project.domain.ProSupervisorItems;
import com.roads.project.mapper.ProCompanyMapper;
import com.roads.project.mapper.ProInstitutionMapper;
import com.roads.project.mapper.ProProjectMapper;
import com.roads.supervisor.domain.SupMeterageDetailConstruction;
import com.roads.supervisor.domain.SupMeterageDetailDefect;
import com.roads.supervisor.domain.SupMeterageDetailOther;
import com.roads.supervisor.domain.SupMeterageDetailWinter;
import com.roads.supervisor.domain.SupMeterageMaster;
import com.roads.supervisor.mapper.SupMeterageDetailConstructionMapper;
import com.roads.supervisor.mapper.SupMeterageDetailDefectMapper;
import com.roads.supervisor.mapper.SupMeterageDetailOtherMapper;
import com.roads.supervisor.mapper.SupMeterageDetailWinterMapper;
import com.roads.supervisor.mapper.SupMeterageMasterMapper;
import com.roads.supervisor.service.ISupMeterageDetailService;
import com.roads.supervisor.service.ISupMeterageMasterService;
import com.roads.system.mapper.SysAnnexFileMapper;
import com.roads.system.mapper.SysUserMapper;
import com.roads.system.service.ISysMessageService;
import com.roads.workflow.domain.WorkflowMeterageNode;
import com.roads.workflow.domain.WorkflowTaskDelivery;
import com.roads.workflow.mapper.WorkflowMeterageNodeMapper;
import com.roads.workflow.service.IWorkflowTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.List;

/**
 * 监理计量Service业务层处理
 * 
 * @author nhp
 * @date 2022-07-12
 */
@Service
public class SupMeterageMasterServiceImpl implements ISupMeterageMasterService {

    @Autowired
    private SupMeterageMasterMapper mapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private ProInstitutionMapper institutionMapper;

    @Autowired
    private ProProjectMapper projectMapper;

    @Autowired
    private ProCompanyMapper companyMapper;

    @Autowired
    private IWorkflowTaskService workflowTaskService;

    @Autowired
    private ISysMessageService messageService;

    @Autowired
    private SysAnnexFileMapper sysAnnexFileMapper;

    @Autowired
    private WorkflowMeterageNodeMapper workflowMeterageNodeMapper;

    @Autowired
    private SupMeterageDetailConstructionMapper detailConstructionMapper;

    @Autowired
    private SupMeterageDetailWinterMapper detailWinterMapper;

    @Autowired
    private SupMeterageDetailDefectMapper detailDefectMapper;

    @Autowired
    private SupMeterageDetailOtherMapper detailOtherMapper;

    @Autowired
    private ISupMeterageDetailService detailService;

    /**
     * 根据主键ID查询详情
     * 
     * @param id 监理计量主键
     * @return 监理计量
     */
    @Override
    public SupMeterageMaster getModelById(Long id) {
        return mapper.getModelById(id);
    }

    /**
     * 查询列表
     * 
     * @param model 监理计量
     * @return 监理计量
     */
    @Override
    public List<SupMeterageMaster> selectModelList(SupMeterageMaster model) {
        return mapper.selectModelList(model);
    }

    /**
     * 校验申请编号是否唯一
     *
     * @param model 工程计量
     * @return 结果
     */
    @Override
    public String checkApplyCodeUnique(SupMeterageMaster model) {
        Long masterId = StringUtils.isNull(model.getMasterId()) ? -1L : model.getMasterId();
        SupMeterageMaster search = mapper.checkApplyCodeUnique(model.getApplyCode());
        if (StringUtils.isNotNull(search) && !search.getMasterId().equals(masterId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 是否计量
     *
     * @param institutionCode 标段编号
     * @param periodName 工期
     * @return 结果
     */
    @Override
    public boolean isMeterage(String institutionCode, String periodName) {
        int count = mapper.getMeterageCount(institutionCode, periodName);
        return count > 0;
    }

    /**
     * 是否计量
     *
     * @param institutionCode 标段编号
     * @return 结果
     */
    @Override
    public boolean isMeterage(String institutionCode) {
        int count = mapper.hasMeterage(institutionCode);
        return count > 0;
    }

    /**
     * 新增
     * 
     * @param model 监理计量
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(SupMeterageMaster model) {
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 获取流程实例
        WorkflowMeterageNode workflowMeterageNode = workflowMeterageNodeMapper.getModelByBeginNodeAndUser(loginUser.getUserName(), Constants.WORKFLOW_TYPE_SUPERVISION);
        // 任务uuid
        String uuid = IdUtils.simpleUuid();
        // 设置 标段名称，项目名称，单位名称
        ProInstitution bid = institutionMapper.getModelByInnerCode(model.getInstitutionCode());
        model.setInstitutionName(bid.getInstitutionName());
        ProProject project = projectMapper.selectProProjectByProjectId(bid.getProjectId());
        model.setProjectId(project.getProjectId());
        model.setProjectName(project.getProjectName());
        ProCompany company = companyMapper.selectProCompanyByCompanyId(bid.getCompanyId());
        model.setCompanyName(company.getCompanyName());
        // 设置当前部门和用户名称
        model.setCurrentDeptName(loginUser.getDept().getDeptName());
        model.setCurrentUser(loginUser.getUserName());
        model.setCurrentDept(loginUser.getDeptId());
        model.setCurrentUserName(loginUser.getNickName());
        model.setCreateBy(loginUser.getUserName());
        model.setCreateTime(DateUtils.getNowDate());
        model.setUuid(uuid);
        model.setWorkflowUuid(workflowMeterageNode.getWorkflowUuid());
        mapper.insert(model);
        // 添加其他支付项目
        ProSupervisorItems search = new ProSupervisorItems();
        search.setProjectId(project.getProjectId());
        search.setComputeMode(Constants.FIXED_VALUE);
        search.setItemStatus(Constants.SUCCESS);
        List<SupMeterageDetailOther> others = detailService.createMeterageOtherList(model, loginUser);
        detailOtherMapper.insertBatch(others);
        // 创建流程
        workflowTaskService.createTask(uuid, Constants.WORKFLOW_TYPE_SUPERVISION, Constants.MENU_TYPE_SUPERVISION, loginUser, workflowMeterageNode);
        return 1;
    }

    /**
     * 修改
     * 
     * @param model 监理计量
     * @return 结果
     */
    @Override
    public int update(SupMeterageMaster model) {
        model.setUpdateTime(DateUtils.getNowDate());
        return mapper.update(model);
    }

    /**
     * 传送
     *
     * @param delivery 传送对象
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int delivery(WorkflowTaskDelivery delivery) {
        // 当前登录用户
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 主表处理 修改当前部门和当前用户
        SupMeterageMaster master = mapper.getModelByUuid(delivery.getTaskUuid());
        // 传送至哪个用户，非当前登录用户
        SysUser deliveryUser = userMapper.selectUserByUserName(delivery.getUser());
        master.setCurrentDept(deliveryUser.getDeptId());
        master.setCurrentDeptName(deliveryUser.getDept().getDeptName());
        master.setCurrentUser(deliveryUser.getUserName());
        master.setCurrentUserName(deliveryUser.getNickName());
        mapper.update(master);
        // 传送明细
        deliveryDetail(master, loginUser, deliveryUser);
        // 流程处理
        workflowTaskService.deliveryTask(delivery, loginUser, deliveryUser);
        // 消息处理
        messageService.handleDeliveryMessage(master.getUuid(), loginUser.getUserName());
        messageService.createDeliveryMessage(
                master.getUuid(),
                deliveryUser.getUserName(),
                "/supervisor/meterage",
                "由" + loginUser.getNickName() + "传送的监理计量",
                loginUser.getUserName());
        return 1;
    }

    /**
     * 传送明细
     * 施工期传送，冬休期传送，缺陷责任期传送
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetail(SupMeterageMaster master, SysUser loginUser, SysUser deliveryUser) {
        // 传送--施工期
        deliveryDetailConstruction(master, loginUser, deliveryUser);
        // 传送--冬休期
        deliveryDetailWinter(master, loginUser, deliveryUser);
        // 传送--缺陷责任期
        deliveryDetailDefect(master, loginUser, deliveryUser);
        // 传送--其他支付项目
        deliveryDetailOther(master, loginUser, deliveryUser);
    }

    /**
     * 传送--施工期
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetailConstruction(SupMeterageMaster master, SysUser loginUser, SysUser deliveryUser) {
        SupMeterageDetailConstruction search = new SupMeterageDetailConstruction();
        search.setMasterId(master.getMasterId());
        search.setUser(loginUser.getUserName());
        // 先删除传送至用户下的数据
        detailConstructionMapper.deleteByUser(master.getMasterId(), deliveryUser.getUserName());
        // 当前登录用户下的数据
        List<SupMeterageDetailConstruction> details = detailConstructionMapper.selectModelList(search);
        for (SupMeterageDetailConstruction detail : details) {
            detail.setDept(deliveryUser.getDeptId());
            detail.setDeptName(deliveryUser.getDept().getDeptName());
            detail.setUser(deliveryUser.getUserName());
            detail.setUserName(deliveryUser.getNickName());
            detail.setIsEdit(Constants.NO);
            detail.setCreateBy(loginUser.getUserName());
        }
        // 批量插入
        if (details.size() > 0) {
            detailConstructionMapper.insertBatch(details);
        }
    }

    /**
     * 传送--冬休期
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetailWinter(SupMeterageMaster master, SysUser loginUser, SysUser deliveryUser) {
        SupMeterageDetailWinter search = new SupMeterageDetailWinter();
        search.setMasterId(master.getMasterId());
        search.setUser(loginUser.getUserName());
        // 先删除传送至用户下的数据
        detailWinterMapper.deleteByUser(master.getMasterId(), deliveryUser.getUserName());
        // 当前登录用户下的数据
        List<SupMeterageDetailWinter> details = detailWinterMapper.selectModelList(search);
        for (SupMeterageDetailWinter detail : details) {
            detail.setDept(deliveryUser.getDeptId());
            detail.setDeptName(deliveryUser.getDept().getDeptName());
            detail.setUser(deliveryUser.getUserName());
            detail.setUserName(deliveryUser.getNickName());
            detail.setIsEdit(Constants.NO);
            detail.setCreateBy(loginUser.getUserName());
        }
        // 批量插入
        if (details.size() > 0) {
            detailWinterMapper.insertBatch(details);
        }
    }

    /**
     * 传送--缺陷责任期
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetailDefect(SupMeterageMaster master, SysUser loginUser, SysUser deliveryUser) {
        SupMeterageDetailDefect search = new SupMeterageDetailDefect();
        search.setMasterId(master.getMasterId());
        search.setUser(loginUser.getUserName());
        // 先删除传送至用户下的数据
        detailDefectMapper.deleteByUser(master.getMasterId(), deliveryUser.getUserName());
        // 当前登录用户下的数据
        List<SupMeterageDetailDefect> details = detailDefectMapper.selectModelList(search);
        for (SupMeterageDetailDefect detail : details) {
            detail.setDept(deliveryUser.getDeptId());
            detail.setDeptName(deliveryUser.getDept().getDeptName());
            detail.setUser(deliveryUser.getUserName());
            detail.setUserName(deliveryUser.getNickName());
            detail.setIsEdit(Constants.NO);
            detail.setCreateBy(loginUser.getUserName());
        }
        // 批量插入
        if (details.size() > 0) {
            detailDefectMapper.insertBatch(details);
        }
    }

    /**
     * 传送--其他支付项目
     *
     * @param master 主表对象
     * @param loginUser 当前登陆用户对象
     * @param deliveryUser 传送至用户
     */
    private void deliveryDetailOther(SupMeterageMaster master, SysUser loginUser, SysUser deliveryUser) {
        SupMeterageDetailOther search = new SupMeterageDetailOther();
        search.setMasterId(master.getMasterId());
        search.setUser(loginUser.getUserName());
        // 先删除传送至用户下的数据
        detailOtherMapper.deleteByUser(master.getMasterId(), deliveryUser.getUserName());
        // 当前登录用户下的数据
        List<SupMeterageDetailOther> details = detailOtherMapper.selectModelList(search);
        for (SupMeterageDetailOther detail : details) {
            detail.setDept(deliveryUser.getDeptId());
            detail.setDeptName(deliveryUser.getDept().getDeptName());
            detail.setUser(deliveryUser.getUserName());
            detail.setUserName(deliveryUser.getNickName());
            detail.setIsEdit(Constants.NO);
            detail.setCreateBy(loginUser.getUserName());
        }
        // 批量插入
        if (details.size() > 0) {
            detailOtherMapper.insertBatch(details);
        }
    }

    /**
     * 批量锁定
     *
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int lock(Long[] ids) {
        SysUser loginUser = userMapper.selectUserById(SecurityUtils.getUserId());
        // 循环处理锁定数据
        for (int i = 0; i < ids.length; i++) {
            long masterId = ids[i];
            // 主表状态处理
            SupMeterageMaster master = mapper.getModelById(masterId);
            master.setStatus(Constants.LOCK);
            mapper.update(master);
            // 完成流程处理
            workflowTaskService.finishTask(master.getUuid(), loginUser);
            // 消息处理
            messageService.handleDeliveryMessage(master.getUuid(), loginUser.getUserName());
        }
        return 1;
    }

    /**
     * 解锁
     *
     * @param master 主表
     * @param id 主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int unlock(SupMeterageMaster master, Long id) {
        master.setStatus(Constants.UNLOCK);
        mapper.update(master);
        // 删除流程完成信息
        workflowTaskService.deleteFinishTask(master.getUuid());
        // 当前数据所在位置的消息改正未读状态
        messageService.updateMessageStatusByUnread(master.getUuid(), master.getCurrentUser());
        return 1;
    }

    /**
     * 批量删除
     * 
     * @param ids 主键集合
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteByIds(Long[] ids) {
        for (int i = 0; i < ids.length; i++) {
            // 查找主表信息
            SupMeterageMaster master = mapper.getModelById(ids[i]);
            String uuid = master.getUuid();
            // 删除主表信息
            mapper.delete(ids[i]);
            // 删除流程
            workflowTaskService.deleteTask(uuid);
            // 删除消息
            messageService.deleteByUuid(uuid);
            // 删除附件记录
            sysAnnexFileMapper.deleteByUuid(uuid);
            // 删除附件文件 其中包含明细里的草图和附件
            String filePath = MasterConfig.getUploadAnnexPath() + "/" + Constants.MENU_TYPE_SUPERVISION + "/" + uuid;
            FileUtils.deleteDirectory(new File(filePath));
            // 删除明细
            deleteDetail(master);
        }
        return 1;
    }

    /**
     * 删除监理计量明细
     *
     * @param master 主表实体
     */
    private void deleteDetail(SupMeterageMaster master) {
        // 删除监理计量--施工期
        deleteDetailConstruction(master);
        // 删除监理计量--冬休期
        deleteDetailWinter(master);
        // 删除监理计量--缺陷责任期
        deleteDetailDefect(master);
    }

    /**
     * 删除监理计量--施工期
     *
     * @param master 主表实体
     */
    private void deleteDetailConstruction(SupMeterageMaster master) {
        // 还原合同清单
        detailConstructionMapper.restore(master.getMasterId(), SecurityUtils.getUsername());
        // 删除施工期计量
        detailConstructionMapper.deleteByMasterId(master.getMasterId());
    }

    /**
     * 删除监理计量--冬休期
     *
     * @param master 主表实体
     */
    private void deleteDetailWinter(SupMeterageMaster master) {
        // 还原合同清单
        detailWinterMapper.restore(master.getMasterId(), SecurityUtils.getUsername());
        // 删除冬休期计量
        detailWinterMapper.deleteByMasterId(master.getMasterId());
    }

    /**
     * 删除监理计量--缺陷责任期
     *
     * @param master 主表实体
     */
    private void deleteDetailDefect(SupMeterageMaster master) {
        // 还原合同清单
        detailDefectMapper.restore(master.getMasterId(), SecurityUtils.getUsername());
        // 删除缺陷责任期计量
        detailDefectMapper.deleteByMasterId(master.getMasterId());
    }

    /**
     * 删除
     * 
     * @param id 监理计量主键
     * @return 结果
     */
    @Override
    public int delete(Long id) {
        return mapper.delete(id);
    }

    /**
     * 查询当前登录用户在监理计量流程开始节点出现的次数
     * @param user 当前登录用户
     * @return 数量
     */
    @Override
    public int getCountWorkflowNodeUserForBeginNode(String user) {
        return mapper.getCountWorkflowNodeUserForBeginNode(user);
    }
}
